using System;
using System.Linq;
using System.Reflection;
using System.Text;

namespace BindingFlagsSnippet
{

    interface A
    {
        void TestA();
    }
    public abstract class B
    {
        public abstract void TestB();
    }
    public abstract class C : B
    {
        public virtual void TestC()
        {

        }
        public virtual void TestD()
        {

        }
    }
    public class MyClass : C, A
    {
        public void TestA()
        {
            throw new NotImplementedException();
        }

        public override void TestB()
        {
            throw new NotImplementedException();
        }
        public override void TestC()
        {
            base.TestC();
        }
        new public void TestD()
        {

        }
        public (bool, bool) TestE()
        {
            return (true, true);
        }
        public string TestF<T>(T t)
        {
            return t.GetType().Name;
        }
        public string TestG(in string a, ref string aa, out string b, string c = "666")
        {
            b = "666";
            return string.Empty;
        }
        public string TestH(params string[] d)
        {
            return string.Empty;
        }
    }
    class Example
    {
        static void Main()
        {
            Type type = typeof(MyClass);
            MethodInfo[] methods = type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Instance);

            foreach (MethodInfo item in methods)
            {
                StringBuilder builder = new StringBuilder();
                builder.Append(GetVisibility(item) + " ");
                builder.Append(item.IsStatic ? "static " : string.Empty);
                builder.Append(IsOver(type, item) + " ");
                builder.Append(GetReturn(item) + " ");
                builder.Append(GetMethodName(item) + " ");
                builder.Append("(" + GetParams(item) + ")");
                Console.WriteLine(builder.ToString());
            }
            Console.ReadKey();
        }
        public static string GetVisibility(MethodInfo method)
        {
            return
                method.IsPublic ? "public" :
                method.IsPrivate ? "private" :
                method.IsAssembly ? "internal" :
                method.IsFamily ? "protected" :
                method.IsFamilyOrAssembly ? "protected internal" :
                null;
        }

        // virtual override  abstract new
        public static string IsOver(Type type, MethodInfo method)
        {
            // 没有相应的信息，说明没有使用以上关键字修饰
            if (!method.IsHideBySig)
                return string.Empty;

            // 是否抽象方法
            if (method.IsAbstract)
                return "abstract";

            // virtual、override、实现接口的方法
            if (method.IsVirtual)
            {
                // 实现接口的方法
                if (method.IsFinal)
                    return string.Empty;
                // 没有被重写，则为 virtual
                if (method.Equals(method.GetBaseDefinition()))
                    return "virtual";
                else
                    return "override";
            }
            // new
            else
            {
                // 如果是当前类型中定义的方法，则只是一个普通的方法
                if (type == method.DeclaringType)
                    return string.Empty;

                return "new";
            }
        }

        // 获取返回类型
        public static string GetReturn(MethodInfo method)
        {
            Type returnType = method.ReturnType;
            ParameterInfo returnParam = method.ReturnParameter;

            if (returnType == typeof(void))
                return "void";
            if (returnType.IsValueType)
            {
                // 判断是否 (type1,type2) 这样的返回
                if (returnParam.ParameterType.IsGenericType)
                {
                    Type[] types = returnParam.ParameterType.GetGenericArguments();
                    string str = "(";
                    for (int i = 0; i < types.Length; i++)
                    {
                        str += types[i].Name;
                        if (i < types.Length - 1)
                            str += ",";
                    }
                    str += ")";
                    return str;
                }
                return returnType.Name;
            }

            // 这里暂不处理复杂的返回类型，例如数组,泛型等。
            return returnType.Name;
        }

        // 判断方法是否为泛型方法，并且返回泛型名称
        public static string GetMethodName(MethodInfo method)
        {
            if (!method.IsGenericMethod)
                return method.Name;
            Type[] types = method.GetGenericArguments();
            string str = method.Name + "<";
            for (int i = 0; i < types.Length; i++)
            {
                str += types[i].Name;
                if (i < types.Length - 1)
                    str += ",";
            }
            str += ">";
            return str;
        }
        public static bool IsPropertyOfAttr(MethodInfo method)
        {
            return method.GetCustomAttributes().Any(x => x.GetType() == typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute));
        }

        // 解析方法的参数
        public static string GetParams(MethodInfo method)
        {
            ParameterInfo[] parameters = method.GetParameters();
            if (parameters.Length == 0)
                return string.Empty;

            int length = parameters.Length - 1;
            StringBuilder str = new StringBuilder();
            for (int i = 0; i <= length; i++)
            {
                str.Append(InRefOut(parameters[i]) + " ");
                // 这里不对复杂类型等做处理
                str.Append(GetParamType(parameters[i]) + " ");
                str.Append(parameters[i].Name);
                str.Append(HasValue(parameters[i]) + " ");
                if (i < length)
                    str.Append(",");
            }
            return str.ToString();
        }

        public static string InRefOut(ParameterInfo parameter)
        {
            // in、ref、out ，类型后面会带有 & 符号
            if (parameter.ParameterType.Name.EndsWith("&"))
            {
                return
                    parameter.IsIn ? "in" :
                    parameter.IsOut ? "out" :
                    "ref";
            }
            if (parameter.GetCustomAttributes().Any(x => x.GetType() == typeof(ParamArrayAttribute)))
                return "params";
            return string.Empty;
        }

        // 获取类型
        public static string GetParamType(ParameterInfo parameter)
        {
            string typeName = parameter.ParameterType.Name;
            if (typeName.EndsWith("&"))
                typeName = typeName.Substring(0, typeName.Length - 1);
            return typeName;
        }

        // 是否为可选参数，是否有默认值
        public static string HasValue(ParameterInfo parameter)
        {
            if (!parameter.IsOptional)
                return string.Empty;
            object value = parameter.DefaultValue;
            return " = " + value.ToString();
        }
    }
}